package xde2d.parser
{
	import away3d.animators.data.UVAnimationFrame;
	import away3d.core.base.CompactSubGeometry;
	import away3d.core.base.Geometry;
	import away3d.core.math.Quaternion;
	import away3d.tools.utils.GeomUtil;
	
	import flash.geom.Matrix3D;
	import flash.geom.Vector3D;
	
	import xde2d.utils.Matrix3DUtils;
	import xde2d.utils.NumberUtil;
	import xde2d.utils.Vector3DUtils;
	
	/**
	 *  @author:Gaara
	 *  2013-3-6
	 * XMesh模型解析器
	 **/
	public class XMeshParser extends BinaryParser
	{
		private static const VERSION_TOKEN:uint = 16;//版本号
		
		private static const NUM_MESHES_TOKEN:uint = 18;//mesh数量
		private static const JOINTS_TOKEN:uint = 20;//骨骼
		private static const MESH_TOKEN:uint = 21;//mesh
		private static const NUM_PARTICLE_SYSTEM:uint = 22;//粒子系统数量
		private static const STATIC_BOUNDINGBOX:uint = 23;//静态包围盒
		private static const NUM_BINDLOOKUPS:uint = 24;//绑定xx
		
		
		private static const MATERIAL_UADDRESSMODE:uint = 0x0100;
		private static const MATERIAL_VADDRESSMODE:uint = 0x0101;
		private static const MATERIAL_RENDERGROUP:uint = 258;
		
		private static const MESH_DIFFUSE_TOKEN:uint = 262;//网格的漫反射贴图
		
		private static const MESH_UVKEYCOUNT:uint = 264;//uv动画帧数量
		
		private static const MATERIAL_AMOUNTNUM:uint = 268;//材质效果数量
		
		private static const MATERIAL_ZBUFFER:uint = 286;
		private static const MATERIAL_ZWRITE:uint = 287;
		private static const MATERIAL_BLENDMODE:uint = 288;//混合模式
		private static const MATERIAL_ALPHA:uint = 289;//材质透明度
		private static const MATERIAL_VERTEXALPHA:uint = 290;//顶点透明度
		private static const MATERIAL_VERTEXNORMAL:uint = 291;//顶点法线
		
		private static const MESH_NUM_BONE_TOKEN:uint = 513;//骨骼数量
		private static const MESH_NUM_VERTS_TOKEN:uint = 515;//mesh顶点数据
		private static const MESH_NUM_TRIS_TOKEN:uint = 517;//三角形数量
		private static const MESH_NUM_WEIGHTS_TOKEN:uint = 519;//权重数量
		private static const MESH_TYPE:uint = 521;//mesh类型
		
		private var _version:int;//版本
		public var isModeFile:Boolean;//是否是模型文件
		
		private var _numJoints:int;//骨骼数量
		private var _numGeometrys:int;//几何图形数量
		private var _numParticleSystem:int;//粒子系统数量
		private var _numBindLookups:int;//绑定xx
		private var _maxJointCount:int;//顶点最大关联的骨骼数
		private var _geometryDataVec:Vector.<GeometryData>;//几何图形数据
		private var _geometry:Geometry;//几何图形对象
		
		
		/** 包围盒 **/
		private var minx_box:Number;
		private var miny_box:Number;
		private var minz_box:Number;
		private var maxx_box:Number;
		private var maxy_box:Number;
		private var maxz_box:Number;
		
		public function XMeshParser()
		{
			super();
		}
		
		override protected function proceedParsing():Boolean
		{
			//类型
			var token:uint;
			while(hasTime())
			{
				token = getNextInt();
				switch(token)
				{
					case VERSION_TOKEN:
						this._version = getNextInt();
						if(this._version != 10 && this._version != 11 &&this._version != 12){
							sendParseError("未知版本号");
						}
						break;
					case NUM_MESHES_TOKEN:
						this._numGeometrys = getNextInt();
						break;
					case NUM_PARTICLE_SYSTEM:
						this._numParticleSystem = getNextInt();
						break;
					case NUM_BINDLOOKUPS:
						this._numBindLookups = getNextInt();
						if (this._numBindLookups > 0){
							
						}
						break;
					case STATIC_BOUNDINGBOX:
						this.parseStaticBoundingBox();
						break;
					case JOINTS_TOKEN:
						_numJoints = getNextInt();
						
						break;
					case MESH_TOKEN:
						this.parseMesh();
						break;
					default:
						if (!this._reachedEOF){
							sendParseError("未知节点");
						}
				}
				this._reachedEOF = (byteData.bytesAvailable == 0);
				if(this._reachedEOF){
					if(_maxJointCount == 0){
						this._geometry = new Geometry();
						if(_geometryDataVec){
							var geometryData:GeometryData;
							var subGeo:CompactSubGeometry;
							for (var i:int = 0; i < _geometryDataVec.length; i++) 
							{
								geometryData = _geometryDataVec[i];
								subGeo = translateGeom(geometryData.vertexData,geometryData.weightData,geometryData.indices,geometryData.hasVertexAlpha);
								
								subGeo.materialName = geometryData.materialName;
								this._geometry.addSubGeometry(subGeo);
							}
						}
					}
					
					finalizeAsset(this._geometry);
					return PARSING_DONE;
				}
			}
			
			return MORE_TO_PARSE;
		}
		
		/** 转换数据为subGeometry **/
		private function translateGeom(vertexDataVec:Vector.<VertexData>, weightData:Vector.<JointData>, indices:Vector.<uint>, hasVertexAlpha:Boolean):CompactSubGeometry
		{
			
			var subGeometry:CompactSubGeometry = new CompactSubGeometry;
			
			var vertexData:VertexData;
			var verts : Vector.<Number> = new Vector.<Number>();
			var uvs : Vector.<Number> = new Vector.<Number>();
			
			for (var i:int = 0; i < vertexDataVec.length; i++) 
			{
				vertexData = vertexDataVec[i];
				verts.push(vertexData.x);
				verts.push(vertexData.y);
				verts.push(vertexData.z);
				
				uvs.push(vertexData.s);
				uvs.push(vertexData.t);
//				if(hasVertexAlpha){
//					uvS.vertexBuffer.writeFloat(vertexData.alpha);
//				}
			}
			
			subGeometry = GeomUtil.constructSubGeometry(verts,indices,uvs,null,null,null,null);
			
/*			subGeometry.updateVertexData(vertexS);
			subGeometry.updateUVData(uvS,hasVertexAlpha?3:2);
			subGeometry.updateIndexData(indices);*/
			return subGeometry;
		}
		
		//解析静态包围盒
		private function parseStaticBoundingBox():void{
			var minX:Number = getNextNumber();
			var minY:Number = getNextNumber();
			var minZ:Number = getNextNumber();
			var maxX:Number = getNextNumber();
			var maxY:Number = getNextNumber();
			var maxZ:Number = getNextNumber();
			
			var matrix3d:Matrix3D = Matrix3DUtils.getMaxToGameMatrix();
			var minVec:Vector3D = matrix3d.transformVector(new Vector3D(minX,minY,minZ));
			var maxVec:Vector3D = matrix3d.transformVector(new Vector3D(maxX,maxY,maxZ));
			this.minx_box = minVec.x;
			this.miny_box = minVec.y;
			this.minz_box = minVec.z;
			this.maxx_box = maxVec.x;
			this.maxy_box = maxVec.y;
			this.maxz_box = maxVec.z;
			var temp:Number;
			if (this.minx_box > this.maxx_box){
				temp = this.minx_box;
				this.minx_box = this.maxx_box;
				this.maxx_box = temp;
			}
			if (this.miny_box > this.maxy_box){
				temp = this.miny_box;
				this.miny_box = this.maxy_box;
				this.maxy_box = temp;
			}
			if (this.minz_box > this.maxz_box){
				temp = this.minz_box;
				this.minz_box = this.maxz_box;
				this.maxz_box = temp;
			}
		}
		
		/** 解析mesh **/
		private function parseMesh():void{
			
//			var bitmapFileMaterial:BitmapFileMaterial = new BitmapFileMaterial("",isModeFile)
			var materialLoad:Boolean;
			
			var meshType:uint = 1;
			var fileName:String;
			var vertexAlpha:Boolean;
			var vertexNormal:Boolean;
			var vertVec:Vector.<VertexData>;
			var indices : Vector.<uint>;
			var weightVec:Vector.<JointData>;
			var uvFrameVec:Vector.<UVFrameData>;
			var amountVec:Vector.<Number>;
			var amountVec2:Vector.<uint>;
			
			var uvFrameNum:int;//包含uv动画帧数
			var flag:uint;//uv动画标志
			var amountNum:int;//效果数量
			
//			var opacityAnimationFrame:OpacityAnimationFrame;
			var uvFrameData:UVFrameData;
			var tempBool:Boolean;
			var tempInt:int;
			var tempStr:String;
			
			var token:uint;
			var bool:Boolean = true;
			while(bool){
				token = getNextInt();
				switch (token){
					case MESH_DIFFUSE_TOKEN:
						if(isModeFile){
							fileName = getNextString();
						}
						else {
							
						}
						materialLoad = true;
						break;
					case  MATERIAL_ALPHA:
						tempBool = getNextBool();
//						bitmapFileMaterial.transparent = tempBool;
						break;
					case  MATERIAL_BLENDMODE:
						tempStr = getNextString();
						if(tempStr == "node"){
//							bitmapFileMaterial.transparent = false;
						}
						else {
//							bitmapFileMaterial.blendMode = tempStr;
//							bitmapFileMaterial.transparent = true;
						}
						break;
					case MATERIAL_UADDRESSMODE:
						tempStr = getNextString();
/*						if (tempStr == "clamp"){
							bitmapFileMaterial.repeat = false;
						} else {
							bitmapFileMaterial.repeat = true;
						}*/
						break;
					case MATERIAL_VADDRESSMODE:
						tempStr = getNextString();
/*						if (tempStr == "clamp"){
							bitmapFileMaterial.repeat = false;
						} else {
							bitmapFileMaterial.repeat = true;
						}*/
						break;
					case MATERIAL_ZBUFFER:
						tempBool = getNextBool();
//						bitmapFileMaterial.zEnable = tempBool;
						break;
					case MATERIAL_ZWRITE:
						tempBool = getNextBool();
//						bitmapFileMaterial.zWriteEnable = getNextBool();
						break;
					case MATERIAL_RENDERGROUP:
						tempInt = getNextInt();
//						bitmapFileMaterial.renderGroupId = getNextInt();
						break;
					case MESH_UVKEYCOUNT:
						uvFrameVec = uvFrameVec || new Vector.<UVFrameData>;
						
						uvFrameNum = getNextInt();
						tempInt = getNextInt();
						tempBool = getNextBool();
//						bitmapFileMaterial.uvInterplote = getNextInt();
						tempInt = getNextInt();
						flag = getNextInt();
						
						var componentNum:int;
						if(flag & 1){
							componentNum++;
						}
						if(flag & 2){
							componentNum++;
						}
						if(flag & 4){
							componentNum++;
						}
						if(flag & 8){
							componentNum++;
						}
						if(flag & 16){
							componentNum++;
						}
						
						for (var i4:int = 0; i4 < uvFrameNum; i4++) 
						{
							uvFrameData = new UVFrameData();
							uvFrameData.index = i4;
							uvFrameData.components = new Vector.<Number>;
							uvFrameData.timestamp = getNextInt();
							for (var i5:int = 0; i5 < componentNum; i5++) 
							{
								uvFrameData.components.push(getNextNumber());
							}
							uvFrameVec.push(uvFrameData);
						}
						break;
					case MATERIAL_AMOUNTNUM:
						amountNum = getNextInt();
						if(amountNum > 0){
							amountVec = new Vector.<Number>(amountNum);
							amountVec2 = new Vector.<uint>;
						}
						for (var i6:int = 0; i6 < amountNum; i6++) 
						{
							amountVec2.push(getNextInt());
							
							amountVec[i6] = getNextNumber();
						}
						break;
					case MESH_TYPE:
						meshType = getNextInt();
						break;
					case MESH_NUM_BONE_TOKEN:
						tempInt = getNextInt();
						for (var i:int = 0; i < tempInt; i++) 
						{
							
						}
						
						break;
					case MATERIAL_VERTEXALPHA:
						vertexAlpha = getNextBool();
//						bitmapFileMaterial.setVertexAlpha(vertexAlpha);
						break;
					case MATERIAL_VERTEXNORMAL:
						vertexNormal = getNextBool();
						break;
					case MESH_NUM_VERTS_TOKEN:
						var vertNum:int = getNextInt();
						vertVec = new Vector.<VertexData>(vertNum,true);
						for (var j:int = 0; j < vertNum; j++) 
						{
							this.parseVertex(j,vertVec,meshType,vertexAlpha,vertexNormal);
						}
						break;
					case MESH_NUM_TRIS_TOKEN:
						var triNum:int = getNextInt();
						indices = new Vector.<uint>();
						for (var k:int = 0; k < triNum; k++) 
						{
							this.parseTri(i,indices);
						}
						break;
					case MESH_NUM_WEIGHTS_TOKEN:
						bool = false;
						var weightNum:int = getNextInt();
						if(weightNum > 0){
							weightVec = new Vector.<JointData>(weightNum,true);
						}
						for (var i2:int = 0; i2 < weightNum; i2++) 
						{
							this.parseJoint(i2, weightVec);
						}
						break;
				}
				
			}
			
			this._geometryDataVec = _geometryDataVec || new Vector.<GeometryData>;
			var index:int = _geometryDataVec.length;
			var geometryData:GeometryData = new GeometryData;
			this._geometryDataVec[index] = geometryData;

			geometryData.meshtype = meshType;
			geometryData.vertexData = vertVec;
			geometryData.weightData = weightVec;
			geometryData.indices = indices;
			geometryData.materialName = fileName;
			geometryData.hasVertexAlpha = vertexAlpha;
			geometryData.hasVertexNormal = vertexNormal;
			
			
			var lastTimestamp:int;
			var uvAnim:UVAnimationFrame;
			if(uvFrameNum != 0){
//				bitmapFileMaterial.squence = new UVAnimationSequence(/*bitmapFileMaterial.name*/);
				for (var i3:int = 0; i3 < uvFrameVec.length; i3++) 
				{
					var offsetU : Number;
					var offsetV : Number;
					var scaleU : Number;
					var scaleV : Number;
					var rotation : Number;
					var timestamp:Number;
					index = 0;
					if(flag & 1){
						offsetU = uvFrameVec[i3].components[index++];
					}
					if(flag & 2){
						offsetV = uvFrameVec[i3].components[index++];
					}
					if(flag & 4){
						scaleU = uvFrameVec[i3].components[index++];
					}
					if(flag & 8){
						scaleV = uvFrameVec[i3].components[index++];
					}
					if(flag & 16){
						rotation = uvFrameVec[i3].components[index++];
					}
					
					timestamp = uvFrameVec[i3].timestamp - lastTimestamp;
					if(timestamp == 0){
						timestamp =1;
					}
					
					lastTimestamp = uvFrameVec[i3].timestamp;
					
					uvAnim = new UVAnimationFrame(offsetU,offsetV,scaleU,scaleV,rotation);
//					bitmapFileMaterial.squence.addFrame(uvAnim,timestamp * (1000/30));
				}
			}
			
			//材质特效
			if(amountNum != 0){
				var lastValue:int;
				var tempInt3:int;
//				bitmapFileMaterial.opacitySquence = new OpacityAnimationSequence(/*bitmapFileMaterial.name*/);
				for (var i7:int = 0; i7 < amountVec.length; i7++) 
				{
					tempInt3 = amountVec2[i7] - lastValue;
					if(tempInt3 == 0){
						tempInt3 = 1;
					}
					
					lastValue = amountVec2[i7];
//					opacityAnimationFrame = new OpacityAnimationFrame(amountVec[i7]);
//					bitmapFileMaterial.opacitySquence.addFrame(opacityAnimationFrame,tempInt3* (1000/30));
				}
			}
			
		}
		
		/**
		 *  功能:解析索引
		 *  参数:
		 **/
		private function parseTri(index:int, indices:Vector.<uint>):void{
			indices.push(getNextInt());
			indices.push(getNextInt());
			indices.push(getNextInt());
		}
		
		/**
		 *  功能:解析骨骼
		 *  参数:
		 **/
		private function parseJoint(index:int, jointVec:Vector.<JointData>):void{
			var joint:JointData = new JointData();
			joint.index = index;
			joint.joint = getNextInt();
			joint.bias = getNextNumber();
			joint.pos = parseVector3D();
			jointVec[joint.index] = joint;
		}
		
		/**
		 *  功能:解析顶点
		 *  参数:
		 **/
		private function parseVertex(index:int,vertVec:Vector.<VertexData>,meshType:int,vertexAlpha:Boolean,vertexNormal:Boolean):void
		{
			var tempP1:Vector3D;
			var tempP2:Vector3D;
			var tempP3:Vector3D;
			var vertexData:VertexData = new VertexData;
			vertexData.index = index;
			vertVec[vertexData.index] = vertexData;
			
			this.parseUV(vertexData);
			var quat:Quaternion = Matrix3DUtils.getMaxToGameRotation();
			if(meshType == 0){
				vertexData.x = getNextNumber();
				vertexData.y = getNextNumber();
				vertexData.z = getNextNumber();
				tempP1 = Vector3DUtils.TEMP_VEC3D;
				quat.rotatePoint(new Vector3D(vertexData.x,vertexData.y,vertexData.z),tempP1);
				vertexData.x = tempP1.x;
				vertexData.y = tempP1.y;
				vertexData.z = tempP1.z;
			}
			else {
				vertexData.startWeight = getNextInt();
				vertexData.countWeight = getNextInt();
				
				if(vertexData.countWeight > this._maxJointCount){
					_maxJointCount = vertexData.countWeight;
				}
			}
			
			if(vertexAlpha){
				vertexData.alpha = getNextNumber();
			}
			
			if(vertexNormal){
				tempP2 = Vector3DUtils.TEMP_VEC3D;
				tempP2.x = getNextNumber();
				tempP2.y = getNextNumber();
				tempP2.z = getNextNumber();
				quat.rotatePoint(new Vector3D(tempP2.x,tempP2.y,tempP2.z),tempP1);
				vertexData.nx = tempP1.x;
				vertexData.ny = tempP1.y;
				vertexData.nz = tempP1.z;
				vertexData.nz = NumberUtil.toLeftHandle(vertexData.nz);
			}
		}
		
		/**
		 *  功能:解析uv
		 *  参数:
		 **/
		private function parseUV(vertexData:VertexData):void{
			vertexData.s = getNextNumber();
			vertexData.t = getNextNumber();
		}
	}
}
import flash.geom.Vector3D;

class VertexData {
	public var index:int;
	public var s:Number;
	public var t:Number;
	public var startWeight:int;
	public var countWeight:int;
	public var x:Number;
	public var y:Number;
	public var z:Number;
	public var nx:Number;
	public var ny:Number;
	public var nz:Number;
	public var alpha:Number;
}

class JointData {
	
	public var index:int;
	public var joint:int;
	public var bias:Number;
	public var pos:Vector3D;
}

/**
 *  功能:几何图形数据
 *  参数:
 **/
class GeometryData {
	public var vertexData:Vector.<VertexData>;
	public var weightData:Vector.<JointData>;
	public var indices:Vector.<uint>;
	public var boneLookup:Vector.<int>;
	public var meshtype:uint;
	public var materialName:String;
	public var hasVertexAlpha:Boolean;
	public var hasVertexNormal:Boolean;
}

/**
 *  功能:uv帧数据
 *  参数:
 **/
class UVFrameData {
	public var timestamp:int;
	public var index:int;
	public var components:Vector.<Number>;
}